<template>
  <Card class="!m-10px">
    <Form :label-col="{ span: 3 }">
      <FormItem label="SPU名称" v-bind="validateInfos.spuName">
        <Input placeholder="请输入SPU名称" v-model:value="spu.spuName" />
      </FormItem>
      <FormItem label="SPU品牌" :wrapper-col="{ span: 6 }" v-bind="validateInfos.tmId">
        <Select placeholder="请选择SPU品牌" v-model:value="spu.tmId">
          <SelectOption v-for="tm in trademarkList" :key="tm.id" :value="tm.id">
            {{ tm.tmName }}
          </SelectOption>
        </Select>
      </FormItem>
      <FormItem label="SPU描述" v-bind="validateInfos.description">
        <Textarea placeholder="请输入SPU描述" v-model:value="spu.description" />
      </FormItem>
      <FormItem label="SPU图片" v-bind="validateInfos.spuImageList">
        <Upload
          v-model:file-list="imageList"
          :action="UPLOAD_URL"
          list-type="picture-card"
          :before-upload="beforeUpload"
          @preview="handlePreview"
          @change="handleChange"
        >
          <div v-if="imageList.length < MAX_UPLOAD_IMG_LENGTH">
            <PlusOutlined class="text-25px" />
          </div>
        </Upload>
        <Modal width="300px" :visible="previewVisible" :footer="null" @cancel="handleCancel">
          <img alt="example" style="width: 100%" :src="previewImage" />
        </Modal>
        <p>只能上传jpg/png文件，且不超过500kb</p>
      </FormItem>
      <FormItem label="销售属性" v-bind="validateInfos.spuSaleAttrList">
        <Select
          v-model:value="selectedSaleAttr"
          :placeholder="`还剩${filterBaseSaleAttrList.length}个销售属性`"
          class="!w-200px !mb-20px !mr-20px"
        >
          <!-- <SelectOption
            v-for="baseSaleAttr in filterBaseSaleAttrList"
            :key="baseSaleAttr.id"
            :value="baseSaleAttr"
          > -->
          <SelectOption
            v-for="baseSaleAttr in filterBaseSaleAttrList"
            :key="baseSaleAttr.id"
            :value="`${baseSaleAttr.id}:${baseSaleAttr.name}`"
          >
            {{ baseSaleAttr.name }}
          </SelectOption>
        </Select>
        <Button type="primary" :disabled="!selectedSaleAttr" @click="addSaleAttr">
          <template #icon><PlusOutlined /></template>
          添加销售属性
        </Button>
        <Table :columns="columns" :dataSource="spu.spuSaleAttrList" bordered :pagination="false">
          <template #bodyCell="{ index, column, record, text }">
            <template v-if="column.dataIndex === 'index'">{{ index + 1 }}</template>
            <template v-if="column.dataIndex === 'spuSaleAttrValueList'">
              <Tag
                v-for="(saleAttrValue, i) in text"
                :key="saleAttrValue.id || saleAttrValue.uid"
                color="blue"
                closable
                @close="delSaleAttrValue(text, i)"
              >
                {{ saleAttrValue.saleAttrValueName }}
              </Tag>
              <Input
                :ref="(input) => (inputsRef[index] = input)"
                v-model:value="saleAttrValueName"
                placeholder="请输入属性值"
                v-if="record.isShowEdit"
                class="!w-150px"
                @blur="addSaleAttrValue(record)"
              />
              <Button v-else @click="showEdit(record, index)">
                <template #icon><PlusOutlined /></template>
                添加属性值
              </Button>
            </template>
            <template v-if="column.dataIndex === 'operator'">
              <Button danger @click="delSaleAttr(index)">
                <template #icon><DeleteOutlined /></template>
              </Button>
            </template>
          </template>
        </Table>
      </FormItem>
      <FormItem :wrapper-col="{ offset: 3 }">
        <Button type="primary" class="mr-10px" @click.prevent="submit">确定</Button>
        <Button @click="emits('setIsShow', CompNames.SPU_LIST)">取消</Button>
      </FormItem>
    </Form>
  </Card>
</template>

<script lang="ts">
  import { defineComponent } from 'vue';

  export default defineComponent({
    name: 'AddOrUpdateSpu',
  });
</script>

<script lang="ts" setup>
  import { ref, reactive, onMounted, computed, nextTick } from 'vue';
  import {
    Card,
    Form,
    FormItem,
    Input,
    Select,
    SelectOption,
    Button,
    Textarea,
    Upload,
    Modal,
    Table,
    message,
    Tag,
  } from 'ant-design-vue';
  import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
  import {
    getBaseSaleAttrListApi,
    saveSpuApi,
    getSpuImageListApi,
    getSpuSaleAttrListApi,
    updateSpuApi,
  } from '/@/api/product/spu';
  import { getAllTrademarkListApi } from '/@/api/product/trademark';
  import {
    BaseSaleAttrListModel,
    SpuModel,
    SpuSaleAttrModel,
    SpuSaleAttrValueListModel,
  } from '/@/api/product/model/spuModel';
  import { TrademarkListModel } from '/@/api/product/model/trademarkModel';
  import { FileInfo, FileItem } from '../../file';
  import { useCategoryStore } from '/@/store/modules/category';
  import { CompNames } from '../types';

  const emits = defineEmits(['setIsShow']);
  const props = defineProps<{
    currentSpu: SpuModel;
  }>();
  // 上传图片地址：从.env.development中加载的
  const UPLOAD_URL = import.meta.env.VITE_GLOB_UPLOAD_URL as string;
  const MAX_UPLOAD_IMG_LENGTH = 10;

  const categoryStore = useCategoryStore();
  /*
      "category3Id": 0,
  "description": "string",
  "id": 0,
  "spuImageList": [
    {
      "imgName": "string",
      "imgUrl": "string",
    }
  ],
  "spuName": "string",
  "spuSaleAttrList": [
    {
      "baseSaleAttrId": 0,
      "id": 0,
      "saleAttrName": "string",
      "spuId": 0,
      "spuSaleAttrValueList": [
        {
          "baseSaleAttrId": 0,
          "id": 0,
          "isChecked": "string",
          "saleAttrName": "string",
          "saleAttrValueName": "string",
          "spuId": 0
        }
      ]
    }
  ],
  "tmId": 0
  */

  const columns = [
    {
      title: '序号',
      className: 'w-70px !text-center',
      dataIndex: 'index',
    },
    {
      title: '属性名',
      className: 'w-100px',
      dataIndex: 'saleAttrName',
    },
    {
      title: '属性值列表',
      dataIndex: 'spuSaleAttrValueList',
    },
    {
      title: '操作',
      className: 'w-70px',
      dataIndex: 'operator',
    },
  ];

  // 表单项数据
  const spu = reactive<SpuModel>(props.currentSpu);
  // 表单验证规则
  const rules = reactive({
    spuName: [{ required: true, message: '请输入SPU名称', trigger: 'blur' }],
    tmId: [{ required: true, message: '请选择SPU品牌' }],
    description: [{ required: true, message: '请输入SPU描述', trigger: 'blur' }],
    spuImageList: [{ required: true, message: '请上传SPU图片', type: 'array' }],
    spuSaleAttrList: [{ required: true, message: '请添加SPU销售属性', type: 'array' }],
  });

  const { validate, validateInfos } = Form.useForm(spu, rules);
  /*
    resetFields   重置表单
    validate      校验表单
    validateInfos 用于绑定表单项验证规则
  */

  const baseSaleAttrList = ref<BaseSaleAttrListModel>([]);
  // 选中的销售属性
  // const selectedSaleAttr = ref<BaseSaleAttrModel | undefined>();
  const selectedSaleAttr = ref<string>('');
  const trademarkList = ref<TrademarkListModel>([]);
  const inputsRef = ref<HTMLInputElement[]>([]);
  // 收集用户输入的销售属性值名称
  const saleAttrValueName = ref<string>('');
  // 预览图片地址
  const previewImage = ref<string>('');
  // 预览图片的对话框显示&隐藏
  const previewVisible = ref<boolean>(false);

  // 格式化数据
  // spu.spuImageList数据格式是为了将来发送请求
  // imageList为了Upload组件需要的
  const imageList = computed(() => {
    return spu.spuImageList.map((img) => {
      return {
        uid: img.uid,
        status: img.status,
        name: img.imgName,
        url: img.imgUrl,
      };
    });
  });

  // 预览图片的回调函数
  const handlePreview = async (file: FileItem) => {
    // if (!file.url && !file.preview) {
    //   file.preview = (await getBase64(file.originFileObj)) as string;
    // }
    previewImage.value = file.url as string;
    previewVisible.value = true;
  };
  // 预览图片对话框隐藏的回调函数
  const handleCancel = () => {
    previewVisible.value = false;
  };
  // 上传图片中触发的函数
  const handleChange = ({ file, fileList }: FileInfo) => {
    // file 当前上传的文件对象
    // fileList 整个上传的文件列表
    // 上传成功没有 file.type file.size
    if (file.type && file.size) {
      const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
      const isLt = file.size / 1024 < 500;
      if (!isJpgOrPng || !isLt) {
        return;
      }
    }

    // 上传过程中要更新多次数据
    spu.spuImageList = fileList.map((img) => {
      return {
        uid: img.uid,
        imgName: img.name,
        /*
          整个handleChange函数会触发两次
            上传中
              没有图片地址 没有img.url
              没有repsonse，response是undefined
            上传成功
              才有图片地址
                上传第一张图片 没有img.url，有img.response.data
                上传第二（3、4..）张图片
                  此时第一张图片只有 img.url
                  上传的第二张图片只有 img.response.data
        */
        // imgUrl: img.url || (img.response && img.response.data),
        imgUrl: img.url || img.response?.data, // 可选链
        status: img.status, // uploading done error
      };
    });
  };
  // 上传图片之前触发的函数：对图片大小和类型进行限制
  const beforeUpload = (file: FileItem) => {
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('只能上传JPG或PNG格式的图片!');
    }
    const isLt = file.size / 1024 < 500;
    if (!isLt) {
      message.error('图片必须小于500KB!');
    }
    return isJpgOrPng && isLt;
  };

  const submit = async () => {
    await validate();
    const id = spu.id;
    const data = {
      ...spu,
      category3Id: categoryStore.getCategory3Id,
    };

    if (id) {
      await updateSpuApi(data);
    } else {
      await saveSpuApi(data);
    }

    message.success(`${id ? '更新' : '添加'}spu成功`);
    emits('setIsShow', CompNames.SPU_LIST);
  };

  // 生命周期可以写多个
  onMounted(async () => {
    baseSaleAttrList.value = await getBaseSaleAttrListApi();
  });
  onMounted(async () => {
    trademarkList.value = await getAllTrademarkListApi();
  });
  onMounted(async () => {
    const id = spu.id as number;
    if (!id) return;
    spu.spuImageList = await getSpuImageListApi(id);
  });
  onMounted(async () => {
    const id = spu.id as number;
    if (!id) return;
    spu.spuSaleAttrList = await getSpuSaleAttrListApi(id);
  });

  // 添加销售属性回调
  const addSaleAttr = () => {
    // const { id, name } = selectedSaleAttr.value as BaseSaleAttrModel;
    const [id, name] = selectedSaleAttr.value.split(':');
    // 将收集到的销售属性添加到spu.spuSaleAttrList
    spu.spuSaleAttrList.push({
      // 基础销售属性的id
      baseSaleAttrId: +id, // 注意类型
      // 基础销售属性的名称
      saleAttrName: name,
      // 销售属性值列表
      spuSaleAttrValueList: [],
      // 是否显示编辑模式
      isShowEdit: false,
    });
    // 清空数据
    // selectedSaleAttr.value = undefined;
    selectedSaleAttr.value = '';
  };
  // 过滤后的baseSaleAttrList
  const filterBaseSaleAttrList = computed(() => {
    return baseSaleAttrList.value.filter((saleAttr) => {
      // 判断 saleAttr 在不在 spu.spuSaleAttrList 中
      // 如果在就要过滤
      // 不在就保留
      return !spu.spuSaleAttrList.some((spuSaleAttr) => {
        return spuSaleAttr.baseSaleAttrId === saleAttr.id;
      });
    });
  });
  // 显示编辑模式
  const showEdit = async (saleAttr: SpuSaleAttrModel, index: number) => {
    saleAttr.isShowEdit = true;
    // 聚焦
    await nextTick();
    inputsRef.value[index].focus();
  };
  // 添加销售属性值
  const addSaleAttrValue = (saleAttr: SpuSaleAttrModel) => {
    if (saleAttrValueName.value) {
      // 添加
      saleAttr.spuSaleAttrValueList.push({
        uid: Date.now(),
        baseSaleAttrId: saleAttr.baseSaleAttrId,
        saleAttrValueName: saleAttrValueName.value,
      });
      // 清空
      saleAttrValueName.value = '';
    }
    // 变成显示模式
    saleAttr.isShowEdit = false;
  };
  // 删除销售属性值
  const delSaleAttrValue = (saleAttrValueList: SpuSaleAttrValueListModel, index: number) => {
    saleAttrValueList.splice(index, 1);
  };
  // 删除销售属性
  const delSaleAttr = (index: number) => {
    spu.spuSaleAttrList.splice(index, 1);
  };
</script>
